package com.gylang.easy.lazy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.gylang.easy.func.Consumer2;
import com.gylang.easy.func.Predicate2;
import com.gylang.easy.util.Asserts;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author gylang
 * data 2021/6/1
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TreeBuilder<ID, T> {

	/** 待构建的树 */
	private Collection<T> dataList;

	/** 生成树 */
	private List<T> tree;
	/** 获取id */
	private Function<T, ID> idFunc;
	/** 获取父级id */
	private Function<T, ID> parentIdFunc;
	/** 顶级判断 默认为 parentId为空 */
	private Predicate<T> topPred;
	/** 子级判断 */
	private Predicate2<T, T> childCheckPred;

	/** 比较排序 */
	private Comparator<T> comparator;
	/** 设置child */
	private Consumer2<T, List<T>> putChild;


	public TreeBuilder<ID, T> buildTree() {

		// 获取顶级节点
		checkParam();
		if (CollUtil.isEmpty(dataList)) {
			tree = new ArrayList<>();
		}

		// 树的构建
		this.topPred = ObjectUtil.defaultIfNull(this.topPred, t -> ObjectUtil.isEmpty(parentIdFunc.apply(t)));
		tree = dataList.stream().filter(this.topPred).sorted(this.comparator)
			.collect(Collectors.toList());

		Map<ID, T> dataMap = dataList.stream().collect(Collectors.toMap(this.idFunc, d -> d));

		recursionTree(tree, dataMap);

		return this;
	}

	public List<T> getTree() {
		return tree;
	}

	private void recursionTree(List<T> parentList, Map<ID, T> dataMap) {

		for (T parent : parentList) {
			Iterator<Map.Entry<ID, T>> iterator = dataMap.entrySet().iterator();
			List<T> childList = new ArrayList<>();
			// 查找判断
			while (iterator.hasNext()) {
				Map.Entry<ID, T> idtEntry = iterator.next();
				// 判断是否为字节
				if (this.childCheckPred.test(parent, idtEntry.getValue())) {
					childList.add(idtEntry.getValue());
					iterator.remove();
				}
			}
			// 排序
			childList.sort(this.comparator);
			this.putChild.accept(parent, childList);
			// 递归查找
			if (CollUtil.isNotEmpty(childList)) {
				recursionTree(childList, dataMap);
			}
		}
	}

	private void checkParam() {
		Asserts.notEmpty(dataList, "数据不能为空");
		Asserts.notNull(idFunc, "ID获取策略不存在");
		Asserts.notNull(parentIdFunc, "父级ID获取策略不存在");
		Asserts.notNull(topPred, "顶级判断策略不能为空");
		Asserts.notNull(childCheckPred, "子级判断策略不能为空");
		Asserts.notNull(putChild, "无法设置");
	}

//	public static void main(String[] args) {
//
//		List<SysMenu> tree = TreeBuilder.<Long, SysMenu>builder()
//			.topPred(c -> 0 == c.getParentId())
//			.childCheckPred((p, c) -> p.getMenuId().equals(c.getParentId()))
//			.comparator(Comparator.comparingInt(o -> Integer.parseInt(o.getOrderNum())))
//			.dataList(JSON.parseObject(json, new TypeReference<List<SysMenu>>() {
//			}))
//			.parentIdFunc(SysMenu::getParentId)
//			.idFunc(SysMenu::getMenuId)
//			.putChild(SysMenu::setChildren)
//			.build()
//			.buildTree()
//			.getTree();
//		System.out.println(tree);
//	}


}
